package com.superme.filemanager.config;

import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import io.minio.MinioClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.SimpleMessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import javax.annotation.Resource;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
@Configuration
public class MyBeans {

    @Resource
    private ThreadPoolConfig threadPoolConfig;

    @Resource
    private RedisConfig redisConfig;

    @Resource
    private MinioConfig minioConfig;
    /**
     * 新的分页插件,一阶减少内存消耗
     * 若要进行分页，请确保你的数据库类型正确配置。
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加分页拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
    /**
     * 自定义rabbitmq消费者消息转换器
     */
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new SimpleMessageConverter());
        //设置手动ack模式 要和yml配置保持一致，不然会覆盖yml文件的配置
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        return factory;
    }
    /**
     * rabbitmq消息转换器
     * @param connectionFactory
     * @return
     */
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate=new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
        return rabbitTemplate;
    }
    /**
     * 线程池配置
     *
     * @return 线程池服务对象
     */
    @Bean
    public ExecutorService executorService() {
        return new ThreadPoolExecutor(threadPoolConfig.getMaxPoolSize(), threadPoolConfig.getMaxPoolSize(), threadPoolConfig.getKeepAliveSeconds(), TimeUnit.SECONDS, new LinkedBlockingQueue<>(threadPoolConfig.getQueueCapacity()), new ThreadPoolExecutor.CallerRunsPolicy());
    }

    /**
     * redisTemplate redis操作对象
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {

        // key   采用StringRedisSerializer
        // value 采用GenericJackson2JsonRedisSerializer

        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 关闭启用默认配置
        template.setEnableDefaultSerializer(false);
        // 连接工厂
        template.setConnectionFactory(factory);
        // key 序列化方式
        template.setKeySerializer(RedisSerializer.string());
        // value 序列化方式
        template.setValueSerializer(RedisSerializer.json());
        // hash key 序列化方式
        template.setHashKeySerializer(RedisSerializer.string());
        // hash value 序列化方式
        template.setHashValueSerializer(RedisSerializer.json());
        // 配置完成
        template.afterPropertiesSet();
        return template;
    }

    /**
     * 连接池
     */
    @Bean
    public JedisPool jedisPool() {
        log.info("JedisPool注入成功！！");
        log.info("redis地址：{}:{}", redisConfig.getHost(), redisConfig.getPort());
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(redisConfig.getMaxIdle());
        jedisPoolConfig.setMaxWaitMillis(redisConfig.getMaxWaitMillis());
        return new JedisPool(jedisPoolConfig, redisConfig.getHost(), redisConfig.getPort(), redisConfig.getTimeout(), redisConfig.getPassword());
    }

    //使用jedisPool注册jedis实例
    @Bean
    public Jedis getJedis() {
        if (jedisPool() != null) {
            return jedisPool().getResource();
        } else {
            return null;
        }
    }

    /**
     * minio客户端
     * @return minio客户端
     */
    @Bean
    public MinioClient minioClient() {
        return MinioClient.builder().endpoint(minioConfig.getEndpoint()).credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey()).build();
    }
}
